-- 运营活动: 团购活动


--[[
{
    cmd_id = 1, -- 命令id，用于批量停止、删除活动 
    act_id = 16, -- 活动id (16 团购活动)
    act_name = "团购活动", -- 活动名称
    act_desc = "活动期间获取经验达到对应档次则可领取丰厚奖励！", -- 活动描述
    beg_time = 1493262000,  -- 活动开始时间(unix timestamp)
    end_time = 1593267400,  -- 活动结束时间(unix timestamp)
    config = -- 配置数据
    {
        itemList =  
        {   
            { weight = 60, type = 0, id = 99, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 86, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 106, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 96, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 60, type = 0, id = 89, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 87, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 107, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20,},
            { weight = 30, type = 0, id = 97, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 60, type = 0, id = 109, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 60, type = 0, id = 129, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 116, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 136, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 126, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 60, type = 0, id = 119, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 117, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 30, type = 0, id = 127, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 60, type = 0, id = 139, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 5, type = 0, id = 159, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 146, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 166, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 156, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 5, type = 0, id = 149, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 147, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 167, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 1, type = 0, id = 157, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
            { weight = 5, type = 0, id = 169, count = 1, buyLimit = 100, nowPrice = 10, oldPrice = 20, },
        },  

        Rewards = 
        {
            {
                buyCount = 100,
                Awards = 
                {       --第一档奖励
                    {type = 0, id = 571, count =10, bind = 1 ,},
                    {type = 0, id = 558, count = 2, bind = 1 ,},
                    {type = 0, id = 563, count = 2, bind = 1 ,},
                    {type = 0, id = 568, count = 2, bind = 1 ,},
                    {type = 0, id = 552, count = 5, bind = 1 ,},
                },
            },
            {
                buyCount = 200,
                Awards = 
                {       --第二档奖励
                    {type = 0, id = 571, count =20, bind = 1 ,},
                    {type = 0, id = 558, count = 4, bind = 1 ,},
                    {type = 0, id = 563, count = 4, bind = 1 ,},
                    {type = 0, id = 568, count = 4, bind = 1 ,},
                    {type = 0, id = 552, count =10, bind = 1 ,},
                },
            },
            {
                buyCount = 300,
                Awards = 
                {       --第三档奖励
                    {type = 0, id = 571, count =30, bind = 1 ,},
                    {type = 0, id = 558, count = 6, bind = 1 ,},
                    {type = 0, id = 563, count = 6, bind = 1 ,},
                    {type = 0, id = 568, count = 6, bind = 1 ,},
                    {type = 0, id = 552, count =15, bind = 1 ,},
                },
            },
        },
    },
}
]]

-- 检查配置是否正确，正确则返回 0，否则返回错误码
function oper_act_63_check_cfg(cfg)
    if cfg == nil then return 20 end
    
    local config = cfg.config
    if config == nil then return 21 end
    
    if config.Rewards == nil then return 23 end
    if type(config.Rewards) ~= "table" then return 24 end
    for idx = 1, #config.Rewards do
        local dayRewards = config.Rewards[idx]
        if dayRewards == nil then return 25 end
        if type(dayRewards) ~= "table" then return 26 end
        local newDayRewards = dayRewards.Awards
        if newDayRewards == nil then return 27 end
        if type(newDayRewards) ~= "table" then return 28 end
        if not oper_act_check_one_award_cfg(newDayRewards) then
            return 22
        end 
    end

    if config.itemList == nil then return 29 end
    if type(config.itemList) ~= "table" then return 30 end

    if not oper_act_check_one_award_cfg(config.itemList) then
            return 22
        end

    return 0
end

-- 安装活动，成功则返回 0，否则返回错误码
function oper_act_63_setup(cfg) 
    return 0
end

-- 卸载活动
function oper_act_63_unsetup(cfg)   
end

-- 活动开始
function oper_act_63_start(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_63_start = 1
    ssVar.oper_act_63_cmd = cfg.cmd_id
    ssVar.oper_act_63_act = cfg.act_id

    local data = gRankMgr_GetValueByIndx(0, RANK_DEFINE_OPERATION_63, 1)

    if data then
        local myData = BaseFuc_unserialize(data)
        if myData and myData.cmd_id and myData.cmd_id == cfg.cmd_id and myData.act_id and myData.act_id == cfg.act_id and
            myData.time and cfg.beg_time <= myData.time and  cfg.end_time > myData.time then
            return
        end
    end

    ssVar.oper_act_63_total_buy_count = 0

    gRankMgr_Clear(RANK_DEFINE_OPERATION_63)
end

-- 活动结束
function oper_act_63_end(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_63_start = nil
    ssVar.oper_act_63_cmd = nil
    ssVar.oper_act_63_act = nil

    if not cfg then return end
    local config = cfg.config
    if not config then return end

    local rankPtr = Ranking.getRanking(RankList[RANK_DEFINE_OPERATION_63].strName)
    local rankCount = Ranking.getRankItemCount(rankPtr)
    for idx = 1, rankCount do
        local item = Ranking.getItemFromIndex(rankPtr, idx-1)
        if item then
            local actorid = tonumber(Ranking.getId(item))
            local data = Ranking.getSub(item, 1)
            local dataTable
            if not data or data == "" then
                dataTable = {}
            else
                dataTable = BaseFuc_unserialize(data)
            end
          
            if dataTable.myBuyCount and dataTable.myBuyCount > 0 then
                local rewardCfg = config.Rewards
                for idx = 1, #config.Rewards do
                    if (dataTable.myDayData and dataTable.myDayData[idx] and dataTable.myDayData[idx] == 1) or
                        ((not dataTable.myDayData or not dataTable.myDayData[idx] or dataTable.myDayData[idx] == 0) and
                            ssVar.oper_act_63_total_buy_count >= config.Rewards[idx].buyCount)
                        then
                        local rewards = rewardCfg[idx].Awards
                        local title = Lang.ScriptTips.Operation171
                        local content = Lang.ScriptTips.Operation172
                        Awards.GiveToMailById(actorid, rewards, title, content, LogIds.OperationLogId063, Lang.LogTips.Operation063, dataTable.vocation, dataTable.sex)
                    end
                end
            end
        end
    end

    ssVar.oper_act_63_total_buy_count = nil
end

-- 打包数据
function oper_act_63_packet_data(sysarg, cfg)

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_63_start then
        return
    end

    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end

    local time = System.getSystemTime()

    if ssVar.oper_act_63_buy_item_time and not System.isUnixTimeSameDay(ssVar.oper_act_63_buy_item_time, time) then
        oper_act_63_new_day_arrive(cfg.act_id) 
        if not ssVar.oper_act_63_buy_item_idx then
            return
        end
        for idx = 1, config.choiceItemNum do
            if not ssVar.oper_act_63_buy_item_idx[idx] then
                return
            end
            local item = config.itemList[ssVar.oper_act_63_buy_item_idx[idx]]
            if not item then
                return
            end
        end
    end

    if not ssVar.oper_act_63_buy_item_idx or (type(ssVar.oper_act_63_buy_item_idx) == 'userdata' and #ssVar.oper_act_63_buy_item_idx ~= config.choiceItemNum) or type(ssVar.oper_act_63_buy_item_idx) ~= 'userdata' then
        oper_act_63_new_day_arrive(cfg.act_id) 
        if not ssVar.oper_act_63_buy_item_idx then
            return
        end
        for idx = 1, config.choiceItemNum do
            if not ssVar.oper_act_63_buy_item_idx[idx] then
                return
            end
            local item = config.itemList[ssVar.oper_act_63_buy_item_idx[idx]]
            if not item then
                return
            end
        end
    end
    
    local actorid = Actor.getActorId(sysarg)
    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_63, 1)
    local myData = BaseFuc_unserialize(data)

    if not myData or myData == "" or myData == 0 then
        myData = {}
    end

    if myData.mySelfTime and not System.isUnixTimeSameDay(myData.mySelfTime, time) then
        myData.myDailyBuyCount = {}
    end

    if not myData.myDailyBuyCount then
        myData.myDailyBuyCount = {}
    end

    if not myData.myBuyCount then
        myData.myBuyCount = 0
    end

    local pack = oper_act_alloc_init_data_packet(sysarg, cfg.cmd_id, cfg.act_id)
    if (pack == nil) then
        return
    end

    DataPack.writeByte(pack, config.choiceItemNum)
    for idx = 1, config.choiceItemNum do
        DataPack.writeByte(pack, ssVar.oper_act_63_buy_item_idx[idx] or 0)
        local item = config.itemList[ssVar.oper_act_63_buy_item_idx[idx]]
        local lastNum = item.buyLimit - (myData.myDailyBuyCount[ssVar.oper_act_63_buy_item_idx[idx]] or 0)
        DataPack.writeShort(pack, lastNum)
        --print("lastNum = "..lastNum)
    end
    DataPack.writeUInt(pack, ssVar.oper_act_63_total_buy_count or 0)
    --print("state = "..(ssVar.oper_act_63_total_buy_count or 0))
    local len = #config.Rewards
    DataPack.writeByte(pack, len)
    for idx = 1, len do
        DataPack.writeByte(pack, idx)
        local state = 0
        if myData.myDayData and myData.myDayData[idx] and myData.myDayData[idx] >= 1 then
            state = myData.myDayData[idx] 
        elseif (not myData.myDayData or not myData.myDayData[idx] or myData.myDayData[idx] == 0) and 
            ssVar.oper_act_63_total_buy_count >= config.Rewards[idx].buyCount and myData.myBuyCount and myData.myBuyCount > 0 then
            state = 1
        end
        DataPack.writeByte(pack, state)
        --print("state = "..state)
    end

    DataPack.flush(pack)

    --DataPack.writeByte(netPack, 1)        -- 活动特有参数
end

-- 操作，返回操作结果，0为成功
function oper_act_63_do(sysarg, cfg, clientPkt)
    if cfg == nil then return end
    
    if cfg.state == nil or cfg.state ~= 1 then -- 不在活动中
        Actor.sendTipmsg(sysarg,Lang.ScriptTips.Operation001, ttFlyTip)
        return
    end
    
    local config = cfg.config
    if config == nil then -- 参数错误
        print("error, oper_act_63_do cfg.config confg error")
        return
    end

    local operType = DataPack.readByte(clientPkt) 
    local Index = DataPack.readByte(clientPkt)

    --print("operType ="..operType)
    --print("Index ="..Index)

    local time = System.getSystemTime()

    --print("time ="..time)

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_63_start then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation004, ttFlyTip)
        return
    end

    if operType == 1 then
        if ssVar.oper_act_63_buy_item_time and not System.isUnixTimeSameDay(ssVar.oper_act_63_buy_item_time, time) then
            --print("oper_act_63_buy_item_time = "..ssVar.oper_act_63_buy_item_time)
            oper_act_63_new_day_arrive(cfg.act_id) 
            if not ssVar.oper_act_63_buy_item_idx then
                return
            end
        end
        local myState = true
        for idx = 1, config.choiceItemNum do
            if ssVar.oper_act_63_buy_item_idx and ssVar.oper_act_63_buy_item_idx[idx] and  ssVar.oper_act_63_buy_item_idx[idx] == Index then
                myState = false
            end
        end
        if myState then
        else
            local actorid = Actor.getActorId(sysarg)
            local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_63, 1)
            local myData = BaseFuc_unserialize(data)

            if not myData then
                myData = {}
            end

            local item = config.itemList[Index]
            if not item then
                Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation015, ttFlyTip)
                return
            end

            if myData.mySelfTime and not System.isUnixTimeSameDay(myData.mySelfTime, time) then
                myData.myDailyBuyCount = {}
            end

            if not myData.myDailyBuyCount then
                myData.myDailyBuyCount = {}
            end

            if not myData.myBuyCount then
                myData.myBuyCount = 0
            end

            if not myData.myDailyBuyCount[Index] then
                myData.myDailyBuyCount[Index] = 0
            end

            if item.buyLimit <= myData.myDailyBuyCount[Index] then
                Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation016, ttFlyTip)
                return 
            end

            if item.nowPrice > Actor.getMoneyCount(sysarg, mtYuanbao) then
                Actor.sendItemLack( sysarg, qatYuanbao, 0, item.nowPrice )
                return
            end

            if not Actor.delMoney( sysarg,mtYuanbao,item.nowPrice,LogIds.OperationLogId063,Lang.LogTips.Operation063) then
                return
            end

            myData.myBuyCount = myData.myBuyCount + 1
            myData.myDailyBuyCount[Index] = myData.myDailyBuyCount[Index] + 1

            ssVar.oper_act_63_total_buy_count = ssVar.oper_act_63_total_buy_count + 1

            --print("myData.myBuyCount ="..myData.myBuyCount)
            --print("myData.myDailyBuyCount[Index] ="..myData.myDailyBuyCount[Index])

            if IsBagGridEnough(sysarg, {item}) then
                GiveCommonAward(sysarg, {item}, LogIds.OperationLogId063, Lang.LogTips.Operation063)
            else
                local actorId = Actor.getActorId(sysarg)
                local title = Lang.ScriptTips.Operation171
                local content = Lang.ScriptTips.Operation172
                local sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
                local vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
                Awards.GiveToMailById(actorId, {item}, title, content, LogIds.OperationLogId063, Lang.LogTips.Operation063, vocation, sex)
            end

            if not myData.cmd_id then
                myData.cmd_id = cfg.cmd_id
                myData.act_id = cfg.act_id
                myData.time = time
            end

            if not myData.sex then
                myData.sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
                myData.vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
            end

            myData.mySelfTime = time

            local newData = BaseFuc_serialize(myData)
            gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_63, 1, newData)

        end
    elseif operType == 2 then
       
        if Index > #config.Rewards then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation005, ttFlyTip)
            return
        end

        local actorid = Actor.getActorId(sysarg)
        local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_63, 1)
        local myData = BaseFuc_unserialize(data)

        if not myData then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation006, ttFlyTip)
            return
        end

        local getState = false
        if myData.myBuyCount and myData.myBuyCount > 0 and ((myData.myDayData and myData.myDayData[Index] and myData.myDayData[Index] == 1) or
            ((not myData.myDayData or not myData.myDayData[Index] or myData.myDayData[Index] == 0) and
                ssVar.oper_act_63_total_buy_count >= config.Rewards[Index].buyCount))
            then
            getState = true
        end

        if not getState  then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation006, ttFlyTip)
            return
        end

        local rewardCfg = config.Rewards

        local rewards = rewardCfg[Index].Awards

        if not myData.myDayData then
            myData.myDayData = {}
        end

        myData.myDayData[Index] = 2
        
        if IsBagGridEnough(sysarg, rewards) then
            GiveCommonAward(sysarg, rewards, LogIds.OperationLogId063, Lang.LogTips.Operation063)
        else
            local actorId = Actor.getActorId(sysarg)
            local title = Lang.ScriptTips.Operation171
            local content = Lang.ScriptTips.Operation172
            local sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
            local vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
            Awards.GiveToMailById(actorId, rewards, title, content, LogIds.OperationLogId063, Lang.LogTips.Operation063, vocation, sex)
        end

        if not myData.cmd_id then
            myData.cmd_id = cfg.cmd_id
            myData.act_id = cfg.act_id
            myData.time = time
        end

        if not myData.sex then
            myData.sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
            myData.vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
        end

        local newData = BaseFuc_serialize(myData)
        gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_63, 1, newData)
    end

    oper_act_63_packet_data(sysarg, cfg)
end


-- 跨天
function oper_act_63_new_day_arrive(act_id) 
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_63_start then
        return
    end
    if ssVar.oper_act_63_act and ssVar.oper_act_63_act == act_id then

        if not ssVar.oper_act_63_cmd then
            return
        end
        
        local cfg = get_oper_act_cfg(ssVar.oper_act_63_cmd, ssVar.oper_act_63_act)
        if not cfg then
            return
        end

        local config = cfg.config
        if not config then
            return
        end 

        local items, itemIndexs = GetItemIdxsRand(config.itemList, config.choiceItemNum)

        ssVar.oper_act_63_buy_item_idx = {}

        if not itemIndexs then
            for idx = 1, config.choiceItemNum do
                ssVar.oper_act_63_buy_item_idx[idx] = idx 
            end
        else
            for idx = 1, config.choiceItemNum do
                ssVar.oper_act_63_buy_item_idx[idx] = itemIndexs[idx] or 0 
            end
        end

        ssVar.oper_act_63_buy_item_time = System.getSystemTime()
    end
end

function gmSetServerCount(num)
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_63_start then
        return
    end
    ssVar.oper_act_63_total_buy_count = num
end





